package sagroup.dracots;

import java.util.HashSet;

import lime2.TupleID;
import sagroup.dracots.TupleType;

/**
 * Record the cost in single period. The cost essentially
 * is the write and read count to a specified type of tuple.
 * @author Zheng Xiang
 *
 */
public class PeriodCost {

	private long writeCount = 0; // update count
	private long readCount = 0; // read count 
	private long remoteTuples = 0;
	
	
	private TupleType type; //tuple type
	private Period period;
	private TupleID tupleId;
	private double adjustedWriteCount; // adjust update count for SO 
    
	 private static double wr = 1; //wr, parameter for read counts
	 private static double ww = 1; //ww, parameter for write counts 
	 private static double e = 0.00000001;  //ww, parameter for not divided by 0 
	
	 private HashSet<TupleID > readSet = new HashSet();
	
	
	 
	 private PeriodCost(int writeTime, int readTime, TupleType type,
			Period period) {
		this.writeCount = writeTime;
		this.readCount = readTime;
		this.type = type;
		this.period = period;
		this.adjustedWriteCount = 0;
	}

	private PeriodCost(int writeTime, int readTime, TupleID tupleId,
			Period period) {
		this.writeCount = writeTime;
		this.readCount = readTime;
		this.type = null;
		this.tupleId = tupleId;
		this.period = period;
		this.adjustedWriteCount = this.writeCount;
	}

	public static PeriodCost createPeriodCost(int writeCount, int readCount,
			TupleType type, Period period) {
		return new PeriodCost(writeCount, readCount, type, period);
	}

	public static PeriodCost createPeriodCost(int writeCount, int readCount,
			TupleID tupleId, Period period) {
		return new PeriodCost(writeCount, readCount, tupleId, period);
	}

	public long getWriteCount() {
		return writeCount;
	}

	public long getReadCount() {
		return readCount;
	}

	public TupleType getType() {
		return type;
	}

	public Period getPeriod() {
		return period;
	}

	public TupleID getTupleId() {
		return tupleId;
	}

	private void incrReadCount(long incrCount) {
		this.readCount += incrCount;
	}
	
	public void incrReadCount(ShareTuple st) {
		if(st.getType().equals(type))
		{
			this.readCount++;
			if(!readSet.contains(st.getVID()))
			{
				readSet.add(st.getVID());
			   // System.out.print(this.period + " / "+st.getType() +" / "+st.getVID());
			}
		}
	}
	
	public long getReadTupleCount()
	{
		return this.readSet.size();
	}
	public void incrWriteCount(long incrCount) {
		this.writeCount += incrCount;
	}

	public void incrAdjustedWriteCount(double writeCount) {
		this.adjustedWriteCount += writeCount;
	}

	
	public double getAdjustedWriteCount() {
		
		return this.adjustedWriteCount;
	}
	
	public void setWriteCount(long counts)
	{
		this.writeCount = counts;
	}
	
	public void setEstimatedTuple(long counts)
	{
		this.remoteTuples = counts;
	}
	
	/**
	 * 
	 * @return read/write proportion of this period
	 * @author  Zheng Xiang
	 */
	
	
	public double getRWProportion()
	{
		double rc = (this.getReadTupleCount() != 0) ?
				this.readCount / (double)this.getReadTupleCount() : 0;
		
		double wc = (this.remoteTuples != 0) ?
		              this.writeCount / (double)this.remoteTuples : 0;
		
		double proportion
		= (rc * wr + e)/ 
		  (rc * wr + wc * ww + 2*e);
		return proportion;
	}
	
	public String toString()
	{
		StringBuffer sb = new StringBuffer();
		sb.append("Period Seq : "+ period.getID()+"-");
		sb.append(" read count : "+ this.readCount);
		sb.append(" USTuple count : "+ this.getReadTupleCount());
		
		sb.append(" write count : "+ this.writeCount);
		sb.append(" ESTuple count : " + this.remoteTuples+"\n");
		return sb.toString();
	}
	
}
